/**
 * genList.c
 *
 *  Created on: 10 Dec 2010
 *      Author: marco
 */

#include "genList.h"

#include <stdlib.h>
#include <errno.h>
#include <stdio.h> //togliere


/**
 *
 * @param compare
 * @param copyk
 * @param copyp
 * @return
 *
 * @retval
 * @retval
 */
list_t * new_List(int (* compare) (void *, void *),void* (* copyk) (void *),void* (*copyp) (void*)){

	list_t *nl;
	nl = malloc(sizeof(list_t));
	if(nl == NULL) {
		return NULL;
	}
	nl->compare = compare;
	nl->copyk = copyk;
	nl->copyp = copyp;
	nl->head = NULL;
	return nl;
}


/**
 *
 * @param pt
 */
void free_List (list_t ** pt){
	elem_t *ep;
	elem_t *tmp;
	if(pt == NULL || *pt == NULL) {
		return;
	}

	ep = (*pt)->head; //errore in free hashtable

	while(ep != NULL){
		tmp = ep;
		free(tmp->key);
		free(tmp->payload);
		free(tmp);
		ep = (ep->next); //errore valgrind


	}

//	free((*pt)->compare);
//	free((*pt)->copyk);
//	free((*pt)->copyp);
	free(*pt);
	*pt = NULL;

}


/**
 *
 * @param t
 * @param key
 * @return
 */
elem_t * find_ListElement(list_t * t,void * key){
	elem_t *tmp;
	if(t == NULL || t->head == NULL){
		return NULL;
	}
	tmp = t->head;
	while( tmp != NULL){
		if(t->compare(key,tmp->key) == 0){
			return tmp;
		}
		if(tmp->next == NULL){ //aggiunto dopo
			return NULL;
		}
		tmp = tmp->next;
	}
	return NULL;
}


/**
 *
 * @param t
 * @param key
 * @param payload
 * @return
 */
int add_ListElement(list_t * t,void * key, void* payload){

	elem_t *new;

	if(t == NULL){
		return -1;
	}
	if(find_ListElement(t,key) != NULL){// è stato trovato un elemento con quella chiave
		//errno = -1;
		return -1;
	}
	new = (elem_t*)malloc(sizeof(elem_t)); //EC
	new->key = t->copyk(key);
	new->payload = t->copyp(payload);
	new->next = t->head;
	t->head = new;
	return 0;
}

/**
 *
 * @param t
 * @param key
 * @return
 */
int remove_ListElement(list_t * t,void * key){
	elem_t *iter;
	elem_t *prev = NULL;

	if(t == NULL || t->head == NULL)
		return -1;

	//controllo elemento in testa
	if(t->compare(t->head->key, key) == 0){
		free(t->head->key);
		free(t->head->payload);
		iter = t->head->next;
		free(t->head);
		t->head = iter;
		return 0;
	}

	//l'elemento non era in testa
	iter = t->head->next;
	prev = t->head;
	while(iter != NULL){
		if(t->compare(iter->key, key) == 0){
			prev->next = iter->next;
			free(iter->key);
			free(iter->payload);
			free(iter);
			iter = NULL;
			return 0;
		}
		prev = iter;
		iter = iter->next;
	}
	return -1;
}




